export enum MultiTenancySides {

  TENANT = 1,

  HOST = 2
}

export interface IMultiTenancy {

  isEnabled: boolean;

  ignoreFeatureCheckForHostUsers: boolean;

  tenantIdCookieName: string;

  setTenantIdCookie(tenantId?: number): void;

  getTenantIdCookie(): number;

}

export interface ILanguageInfo {

  name: string;

  displayName: string;

  icon: string;

  isDefault: boolean;

  isDisabled: boolean;

}

export interface ILocalizationSource {

  name: string;

  type: string;

}

interface ILanguageValues {
  [key: string]: string;
  value: string;
}

export interface ILocalization {
  languages: ILanguageInfo[];

  currentLanguage: ILanguageInfo;

  sources: ILocalizationSource[];

  defaultSourceName: string;

  values: { [key: string]: ILanguageValues };

  abpWeb: (key: string) => string;

  localize(key: string, sourceName: string): string;

  getSource(sourceName: string): (key: string) => string;

  isCurrentCulture(name: string): boolean;
}

export interface IAbpSession {

  readonly userId?: number;

  readonly tenantId?: number;

  readonly impersonatorUserId?: number;

  readonly impersonatorTenantId?: number;

  readonly multiTenancySide: MultiTenancySides;

}

export interface IAuth {

  allPermissions: { [name: string]: boolean };

  grantedPermissions: { [name: string]: boolean };

  isGranted(permissionName: string): boolean;

  isAnyGranted(...args: string[]): boolean;

  areAllGranted(...args: string[]): boolean;

  tokenCookieName: string;

  /**
   * Saves auth token.
   * @param authToken The token to be saved.
   * @param expireDate Optional expire date. If not specified, token will be deleted at end of the session.
   */
  setToken(authToken: string, expireDate?: Date): void;

  getToken(): string;

  clearToken(): void;

  refreshTokenCookieName: string;

  /**
   * Saves refreshToken token.
   * @param refreshToken The token to be saved.
   * @param expireDate Optional expire date. If not specified, token will be deleted at end of the session.
   */
  setRefreshToken(refreshToken: string, expireDate?: Date): void;

  getRefreshToken(): string;

  clearRefreshToken(): void;
}
export interface IFeature {

  value: string;

}
export interface IFeatures {

  allFeatures: { [name: string]: IFeature };

  get(name: string): IFeature;

  getValue(name: string): string;

  isEnabled(name: string): boolean;

}

export enum settingScopes {

  Application = 1,

  Tenant = 2,

  User = 4
}
export interface ISetting {

  values: { [name: string]: string };

  get(name: string): string;

  getBoolean(name: string): boolean;

  getInt(name: string): number;


}
export interface IMenu {

  name: string;

  displayName?: string;

  customData?: any;

  items: IMenuItem[];

}

export interface IMenuItem {

  name: string;

  order: number;

  displayName?: string;

  icon?: string;

  url?: string;

  customData?: any;

  items: IMenuItem[];

}
export interface INav {
  menus: { [name: string]: IMenu };
}

export enum severity {
  INFO,
  SUCCESS,
  WARN,
  ERROR,
  FATAL
}

export enum userNotificationState {
  UNREAD,
  READ
}
//TODO: We can extend this interface to define built-in notification types, like ILocalizableMessageNotificationData 
interface INotificationData {

  type: string;

  properties: any;
}
interface INotification {

  id: string;

  notificationName: string;

  severity: severity;

  entityType?: any;

  entityTypeName?: string;

  entityId?: any;

  data: INotificationData;

  creationTime: Date;

}

interface IUserNotification {

  id: string;

  userId: number;

  state: userNotificationState;

  notification: INotification;
}

export interface INotifications {

  messageFormatters: any;

  getUserNotificationStateAsString(userNotificationState: userNotificationState): string;

  getUiNotifyFuncBySeverity(severity: severity): (message: string, title?: string, options?: any) => void;

  getFormattedMessageFromUserNotification(userNotification: IUserNotification): string;

  showUiNotifyForUserNotification(userNotification: IUserNotification, options?: any): void;

}

export enum LogLevels {
  DEBUG,
  INFO,
  WARN,
  ERROR,
  FATAL
}
export interface ILog {

  level: LogLevels;

  log(logObject?: any, logLevel?: LogLevels): void;

  debug(logObject?: any): void;

  info(logObject?: any): void;

  warn(logObject?: any): void;

  error(logObject?: any): void;

  fatal(logObject?: any): void;

}


export interface INotify {

  info(message: string, title?: string, options?: any): void;

  success(message: string, title?: string, options?: any): void;

  warn(message: string, title?: string, options?: any): void;

  error(message: string, title?: string, options?: any): void;

}

export interface IMessage {

  //TODO: these methods return jQuery.Promise instead of any. fix it.

  info(message: string, title?: string, options?: any): any;

  success(message: string, title?: string, options?: any): any;

  warn(message: string, title?: string, options?: any): any;

  error(message: string, title?: string, options?: any): any;

  confirm(message: string, title?: string, callback?: (result: boolean) => void, options?: any): any;

}



interface ui {

  block(elm?: any): void;

  unblock(elm?: any): void;

  setBusy(elm?: any, optionsOrPromise?: any): void;

  clearBusy(elm?: any): void;

}

interface event {

  on(eventName: string, callback: (...args: any[]) => void): void;

  off(eventName: string, callback: (...args: any[]) => void): void;

  trigger(eventName: string, ...args: any[]): void;

}

interface INameValue {
  name: string;
  value?: any;
}



interface IClockProvider {

  supportsMultipleTimezone: boolean;

  now(): Date;

  normalize(date: Date): Date;

}

interface ITimeZoneInfo {

  windows: {

    timeZoneId: string;

    baseUtcOffsetInMilliseconds: number;

    currentUtcOffsetInMilliseconds: number;

    isDaylightSavingTimeNow: boolean;

  },

  iana: {

    timeZoneId: string;

  }

}



interface ITiming {

  utcClockProvider: IClockProvider;

  localClockProvider: IClockProvider;

  unspecifiedClockProvider: IClockProvider;

  convertToUserTimezone(date: Date): Date;

  timeZoneInfo: ITimeZoneInfo;
}

interface IClock {

  provider: IClockProvider;

  now(): Date;

  normalize(date: Date): Date;

}

interface IAntiForgery {

  tokenCookieName: string;

  tokenHeaderName: string;

  getToken(): string;
}
interface ISecurity {

  antiForgery: IAntiForgery

}

export declare interface Abp {

  appPath: string;
  domain: string;
  pageLoadTime: Date;

  multiTenancy: IMultiTenancy

  session: IAbpSession;
  localization: ILocalization
  auth: IAuth
  features: IFeatures
  setting: ISetting
  nav: INav
  notifications: INotifications
  log: ILog;
  notify: INotify
  message: IMessage
  timing: ITiming
  clock: IClock
  security: ISecurity
}